Skip to content

fix(ui): keep phone status-bar safe-area when header collapses#1234

Merged
BigSimmo merged 8 commits into
mainfrom
cursor/fix-phone-safe-area-collapse-5b1d
Jul 25, 2026
Merged

fix(ui): keep phone status-bar safe-area when header collapses#1234
BigSimmo merged 8 commits into
mainfrom
cursor/fix-phone-safe-area-collapse-5b1d

Conversation

@BigSimmo

@BigSimmo BigSimmo commented Jul 25, 2026

Copy link
Copy Markdown
Owner

Summary

Two phone chrome bugs from the user’s Forms / service screenshots:

  1. Search modes (Forms, etc.) — header and footer stayed visible while scrolling results because every submit kept focus=1 on the dock. Composer focus pins both chrome edges, so hide-on-scroll never fired and the bottom white safe-area rail stayed on screen.
  2. Info pages — header could hide, but the bottom dock’s hide transform used env(safe-area-inset-bottom) while the visible pad used var(--safe-area-bottom), so a white rail could peep; also covered by the same focus/scroll release path when the detail footer search is shown.

Also keeps the earlier top status-bar safe-area spacer so collapsed headers never release the OS inset.

Fixes

  • GlobalSearchShell: do not pass focus: true with run: true; gate autofocus on !hasSubmittedModeSearch; blur on submitted views and when the result canvas scrolls
  • Dock hide transform uses var(--safe-area-bottom)
  • Always-on chrome-safe-area-top outside the collapse/translate hide path
  • Contract + Playwright guards (Forms hide after submit; service-detail status-bar band)

Forms results after scroll — header and footer dock hidden

Test plan

  • npx vitest run tests/header-scroll-hide-contract.test.ts (12/12)
  • npm run test:e2e -- tests/ui-phone-scroll.spec.ts -g "forms search hides|status-bar inset" --project=chromium (2/2)
  • Broader verify:ui before merge if desired

RAG impact: no retrieval behaviour change — UI chrome focus/safe-area only.

To show artifacts inline, enable in settings.

Open in Web Open in Cursor 

Summary by CodeRabbit

  • Bug Fixes

    • Improved mobile search result scrolling so headers and bottom docks hide and reveal consistently.
    • Prevented search composer focus from keeping navigation chrome pinned during result scrolling.
    • Preserved the device status-bar safe area while collapsing mobile headers.
    • Improved bottom dock transitions to account for safe-area spacing consistently.
  • Documentation

    • Clarified scrolling, safe-area, focus, and header/footer visibility behavior.

Hide-on-scroll was reclaiming the entire header including the OS top
inset, so scrolled service-detail text painted under the system status
bar. Keep an always-on chrome-safe-area-top spacer outside the 0fr /
translate hide path, and guard it with contract + phone Playwright proof.

Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>
@supabase

supabase Bot commented Jul 25, 2026

Copy link
Copy Markdown

This pull request has been ignored for the connected project sjrfecxgysukkwxsowpy because there are no changes detected in supabase directory. You can change this behaviour in Project Integrations Settings ↗︎.


Preview Branches by Supabase.
Learn more about Supabase Branching ↗︎.

@coderabbitai

coderabbitai Bot commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The search chrome contract now preserves the top OS safe-area band during header collapse, releases composer focus in submitted result views, uses shared bottom safe-area calculations for dock hiding, and adds contract and mobile UI coverage.

Changes

Search chrome behavior

Layer / File(s) Summary
Preserve the top safe-area band
src/components/clinical-dashboard/master-search-header.tsx, docs/search-chrome-behaviour.md, tests/header-scroll-hide-contract.test.ts, tests/ui-phone-scroll.spec.ts
The collapsing header now places chrome-safe-area-top outside the collapse wrapper, with safe-area-based sticky positioning and updated contract coverage.
Release focus in submitted result views
src/components/clinical-dashboard/global-search-shell.tsx, tests/header-scroll-hide-contract.test.ts, tests/ui-phone-scroll.spec.ts
Submitted searches disable composer autofocus, blur focused inputs during result scrolling, and verify that hidden headers and docks release their reserved space.
Align dock hide transforms with safe-area variables
src/app/globals.css, docs/search-chrome-behaviour.md
Mobile dock and compare-addon translations use --safe-area-bottom, with documentation covering hide/reveal and focus constraints.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

Suggested labels: codex

Suggested reviewers: cursoragent

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description has a summary and tests, but it does not follow the required template sections for Verification and Risk/Rollout. Add the template's Verification section with the required checkboxes or explicit not-run notes, and include Risk/Rollout (and Clinical Governance if applicable).
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately summarizes the main UI safe-area/header-collapse fix.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch cursor/fix-phone-safe-area-collapse-5b1d

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown
Contributor

CI triage

CI failed on this PR. Automated classification of the 3 failed job(s):

  • Production UIneeds investigation: inspect the failing step and uploaded diagnostics; rerun only after classifying the cause.
  • Static PR checksneeds investigation: inspect the failing step and uploaded diagnostics; rerun only after classifying the cause.
  • PR requiredneeds investigation: inspect the failing step and uploaded diagnostics; rerun only after classifying the cause.

Compared with main CI run #5694 (success).

Classification is evidence routing, not permission to ignore a failure. Exact quarantined Playwright identities remain governed by the flake ledger.

cursoragent and others added 6 commits July 25, 2026 19:36
Keep the status-bar band above the 0fr header's upward layout box and
assert geometry (main/content top >= safe-area) instead of hit-testing
through the spacer.

Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>
Submitted shell searches kept focus=1 on the dock input, which pins both
chrome edges and leaves the header plus bottom white safe-area rail stuck
visible. Stop carrying focus into run=1 views, blur on result scroll, and
clear the hidden dock with var(--safe-area-bottom).

Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>
@BigSimmo
BigSimmo marked this pull request as ready for review July 25, 2026 21:24
@BigSimmo
BigSimmo enabled auto-merge (squash) July 25, 2026 21:24

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/components/clinical-dashboard/global-search-shell.tsx (1)

548-594: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicated blur-on-scroll threshold logic.

The same condition (target.scrollTop > 8 && inputRef.current && document.activeElement === inputRef.current → blur) appears in both handleMainScroll (Lines 553-555) and the nested-scroller onScrollCapture (Lines 579-581). Consider extracting a small helper (e.g. blurComposerIfPastThreshold(target)) so the two sites can't drift if the threshold or condition changes later.

♻️ Proposed refactor
+  function blurComposerIfPastThreshold(target: HTMLElement) {
+    if (target.scrollTop > 8 && inputRef.current && document.activeElement === inputRef.current) {
+      inputRef.current.blur();
+    }
+  }
+
   function handleMainScroll(event: UIEvent<HTMLDivElement>) {
     const target = event.currentTarget;
-    if (target.scrollTop > 8 && inputRef.current && document.activeElement === inputRef.current) {
-      inputRef.current.blur();
-    }
+    blurComposerIfPastThreshold(target);
     chromeScrollHide.reportScroll({...});
   }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/clinical-dashboard/global-search-shell.tsx` around lines 548 -
594, Extract the shared focus-release condition from handleMainScroll and the
nested-scroller onScrollCapture callback into a small helper such as
blurComposerIfPastThreshold, accepting the scroll target and performing the
existing blur behavior. Replace both duplicated conditionals with calls to this
helper while preserving the current threshold and focus checks.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/components/clinical-dashboard/global-search-shell.tsx`:
- Around line 548-594: Extract the shared focus-release condition from
handleMainScroll and the nested-scroller onScrollCapture callback into a small
helper such as blurComposerIfPastThreshold, accepting the scroll target and
performing the existing blur behavior. Replace both duplicated conditionals with
calls to this helper while preserving the current threshold and focus checks.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 9e6664ad-426e-4cae-8d18-0da451f5ce59

📥 Commits

Reviewing files that changed from the base of the PR and between ffd8663 and e99df87.

📒 Files selected for processing (6)
  • docs/search-chrome-behaviour.md
  • src/app/globals.css
  • src/components/clinical-dashboard/global-search-shell.tsx
  • src/components/clinical-dashboard/master-search-header.tsx
  • tests/header-scroll-hide-contract.test.ts
  • tests/ui-phone-scroll.spec.ts

@BigSimmo
BigSimmo merged commit 8004a2e into main Jul 25, 2026
22 checks passed
@BigSimmo
BigSimmo deleted the cursor/fix-phone-safe-area-collapse-5b1d branch July 25, 2026 21:38
BigSimmo added a commit that referenced this pull request Jul 26, 2026
Resolve search-chrome conflicts by keeping main's sticky-stack top-bar
hide behaviour from #1238/#1234, which supersedes the page-anchored
composer approach on this branch.

Co-authored-by: Cursor <cursoragent@cursor.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants